//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include "CEnumerator.h"
#include <elastos.h>
#include <elapi.h>
#include <elacs.h>

UInt32 __CObjectEnumerator::AddRef()
{
    return (UInt32)m_cRef.Increment();
}

UInt32 __CObjectEnumerator::Release()
{
    Int32 nRef = m_cRef.Decrement();

    if (0 == nRef) {
        delete this;
        DecrementDllLockCount();
    }
    return nRef;
}

PInterface __CObjectEnumerator::Probe(
    REIID riid)
{
    if (EIID_IInterface == riid) {
        return (IInterface *)this;
    }
    else if (EIID_IObjectEnumerator == riid) {
        return (IObjectEnumerator *)this;
    }
    else if (EIID_CLASS_INFO == riid) {
        return (IInterface *)&ECLSID_CObjectEnumerator;
    }
    else if (EIID_INTERFACE_INFO == riid) {
        return (IInterface *)&EIID_IObjectEnumerator;
    }
    else {
        return NULL;
    }
}

ECode __CObjectEnumerator::Aggregate(
    AggregateType type, PInterface pObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode __CObjectEnumerator::GetDomain(
    PInterface *ppObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode __CObjectEnumerator::Current(
    /* [out] */ PInterface *ppObj)
{
    if (NULL == ppObj) return E_INVALID_ARGUMENT;
    if (NULL == m_pCurrent || m_pHeader == m_pCurrent) {
        return E_INVALID_OPERATION;
    }

    Void * pContext = _Elastos_CriticalSection_Enter(m_pLock);

    if (m_nOrigState != *m_pState) {
        m_pCurrent = NULL;
        _Elastos_CriticalSection_Leave(m_pLock, pContext);
        return E_INVALID_OPERATION;
    }

    *ppObj = m_pCurrent->m_pObject;
    m_pCurrent->m_pObject->AddRef();
    _Elastos_CriticalSection_Leave(m_pLock, pContext);
    return NOERROR;
}

ECode __CObjectEnumerator::MoveNext(Boolean *pSucceeded)
{
    if (NULL == m_pCurrent) {
        *pSucceeded = FALSE;
        return E_INVALID_OPERATION;
    }

    Void * pContext = _Elastos_CriticalSection_Enter(m_pLock);

    if (m_nOrigState != *m_pState) {
        m_pCurrent = NULL;
        _Elastos_CriticalSection_Leave(m_pLock, pContext);
        *pSucceeded = FALSE;
        return E_INVALID_OPERATION;
    }

    if (m_pCurrent == m_pHeader->Prev()) {
        m_pCurrent = NULL;
        _Elastos_CriticalSection_Leave(m_pLock, pContext);
        *pSucceeded = FALSE;
        return NOERROR;
    }

    m_pCurrent = (ObjectNode *)m_pCurrent->Next();
    _Elastos_CriticalSection_Leave(m_pLock, pContext);
    *pSucceeded = TRUE;
    return NOERROR;
}

ECode __CObjectEnumerator::Reset()
{
    m_pCurrent = m_pHeader;
    m_nOrigState = *m_pState;
    return NOERROR;
}
